/**
 * 文件上传 - 服务器上传
 */
import { server_upload_file, server_request } from "../../utils/request";
import uploadConfig from "../../config/upload";
import async from 'async';


/*
    单次上传
 */
function onceUploadFile( file, config){
    let action = uploadConfig.server.action;

    let formData = new FormData();
    formData.append('file', file, file.name );
    if( typeof config.uploadParam == "function"){
        formData = config.uploadParam( formData);
    }

    server_upload_file( 
        action, 
        formData,
        (e) => {
            typeof config.progress == "function" && config.progress( { percent: e.percent});
        }

    ).then( (res)=>{

        if( res.code == 200){
            typeof config.success == "function" && config.success( res);
        }else{
            typeof config.failure == "function" && config.failure( {code: 500, msg: "上传失败", data: res});
        }

    }).catch( (e) => {
        console.error( "utils/upload/server.js upload fail", e);
        typeof config.failure == "function" && config.failure( {code: 500, msg: "上传失败", data: e});
    });
}


/*
    分片上传
 */
function multipartUpload( file, config){
    let uploadId = Date.now().toString( 36) + "_" + ( Math.random().toString( 36).substr( 3, 8));
    let key = file.name;
    var tasks = getTasks( file, uploadId, key);

    console.log( "tasks" , tasks);
    let state = {
        lengthComputable: true,
        loaded: 0,
        total: tasks.length
    };

    let deferred = new Promise( (resolve, reject) => {
        let THREADS = 2; // 同时上传的分块数量
        async.mapLimit(
            tasks, 
            THREADS, 
            uploadPartFile(state, {
                progress: (e)=>{
                    typeof config.progress == "function" && config.progress( { percent: e.percent});
                }
            }), 
            (err, results)=>{
                // console.log( "on finish", err, results, state);
                if (err) {
                    reject(err);
                } else {
                    resolve(results);
                }
            }
        );
    });

    deferred.catch( (e)=>{
        typeof config.failure == "function" && config.failure( e);
    });
    deferred.then( (e) =>{
        // 所有分片全部上传完成，进行合并
        console.log( "upload part finish");
        return server_request( 
            uploadConfig.server.action,
            {
                type: "mergePart",
                uploadId: uploadId,
                fileName: key,
                partSize: state.total,
            }
        );
    }).then( ( res)=>{
        if( res.code == 200){
            typeof config.success == "function" && config.success( res);
        }else{
            typeof config.failure == "function" && config.failure( res);
        }
    }).catch( (e) => {
        typeof config.failure == "function" && config.failure( "上传失败");
    });
}

/* 给文件分片 */
function getTasks(file, uploadId, key) {

    let PART_SIZE = 1 * 1024 * 1024; // 指定分块大小  1Mb 一块

    let leftSize = file.size;
    let offset = 0;
    let partNumber = 1;

    let tasks = [];

    while (leftSize > 0) {
        let partSize = Math.min(leftSize, PART_SIZE);
        tasks.push({
            file: file,
            uploadId: uploadId,
            key: file.name,
            partNumber: partNumber,
            partSize: partSize,
            start: offset,
            stop: offset + partSize - 1
        });

        leftSize -= partSize;
        offset += partSize;
        partNumber += 1;
    }
    // console.log( "task", tasks);
    return tasks;
}

function uploadPartFile( state, config){
    return (task, callback) =>{
        let blob = task.file.slice(task.start, task.stop + 1);
        // console.log( "upload blob", blob);
        // debugger;

        onceUploadFile( blob, {
            uploadParam: (formData)=>{
                formData.append( "type", "multiPart");
                formData.append( "uploadId", task.uploadId);
                formData.append( "partNumber", task.partNumber);
                formData.append( "partSize", task.partSize);
                formData.append( "fileName", task.key);
                return formData;
            },
            progress: (e)=>{},
            success: (e)=>{
                ++state.loaded;
                typeof config.progress == "function" && config.progress( ( state.loaded / state.total ) * 100);
                callback( null, e);
            },
            failure: (e)=>{
                callback(e);
            }
        });

        // client.uploadPartFromBlob(task.bucketName, task.key, task.uploadId, task.partNumber, task.partSize, blob)
        //     .then(function(res) {
        //         ++state.loaded;
        //         console.log( "onProgress", state);
        //         http.onProgress( { percent: Math.floor( ( state.loaded / state.total ) * 100)});
        //         callback(null, res);
        //     })
        //     .catch(function(err) {
        //         callback(err);
        //     });
    };
}


export default function uploadFile( file, config) {
    let upconfig = uploadConfig.server;
    let progress, success, failure;

    progress = config.progress;
    success = config.success;
    failure = config.failure;

    if( upconfig.multipart){
        multipartUpload(
            file, 
            {
                progress, 
                success, 
                failure
            }
        );
    }else{
        onceUploadFile( 
            file, 
            {
                progress, 
                success, 
                failure
            }
        );
        // onceUploadFile( file, progress, success, failure);
    }
}
